import Axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type CustomParamsSerializer
} from "axios";
import type {
  PureHttpError,
  RequestMethods,
  PureHttpResponse,
  PureHttpRequestConfig
} from "./types.d";
import { stringify } from "qs";
import NProgress from "../progress";
import { ElLoading } from "element-plus";
import { getToken, formatToken } from "@/utils/auth";
import { message } from "@/utils/message";
import { useUserStoreHook } from "@/store/modules/user";
import {
  handleHttpError,
  handleBusinessError,
  redirectToLogin
} from "./errorHandler";

// 相关配置请参考：www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
  // 新增基础API地址
  baseURL: import.meta.env.DEV ? "/temp" : import.meta.env.VITE_APP_BASE_API, // 开发环境用代理，生产环境用真实地址
  // 请求超时时间
  timeout: 10000,
  headers: {
    Accept: "application/json, text/plain, */*",
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest"
  },
  // 数组格式参数序列化
  paramsSerializer: {
    serialize: stringify as unknown as CustomParamsSerializer
  }
};

class PureHttp {
  constructor() {
    this.httpInterceptorsRequest();
    this.httpInterceptorsResponse();
  }

  /** `token`过期后，暂存待执行的请求 */
  private static requests = [];
  private static loadingInstance: any = null;
  private static loadingCount = 0; // 新增请求计数器

  /** 防止重复刷新`token` */
  private static isRefreshing = false;

  /** 初始化配置对象 */
  private static initConfig: PureHttpRequestConfig = {};

  /** 保存当前`Axios`实例对象 */
  private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);

  /** 重连原始请求 */
  private static retryOriginalRequest(config: PureHttpRequestConfig) {
    return new Promise(resolve => {
      PureHttp.requests.push((token: string) => {
        config.headers["Authorization"] = formatToken(token);
        resolve(config);
      });
    });
  }
  /** 请求拦截 */
  private httpInterceptorsRequest(): void {
    PureHttp.axiosInstance.interceptors.request.use(
      async (config: PureHttpRequestConfig): Promise<any> => {
        // 开启进度条动画
        NProgress.start();
        // 新增计数器逻辑
        if (PureHttp.loadingCount === 0) {
          // 全屏加载组件
          PureHttp.loadingInstance = ElLoading.service({
            fullscreen: true,
            background: "rgba(110, 110, 110, 0.2)" // 添加背景颜色配置
          });
        }
        PureHttp.loadingCount++;
        // 优先判断post/get等方法是否传入回调，否则执行初始化设置等回调
        if (typeof config.beforeRequestCallback === "function") {
          config.beforeRequestCallback(config);
          return config;
        }
        if (PureHttp.initConfig.beforeRequestCallback) {
          PureHttp.initConfig.beforeRequestCallback(config);
          return config;
        }
        /** 请求白名单，放置一些不需要`token`的接口（通过设置请求白名单，防止`token`过期后再请求造成的死循环问题） */
        const whiteList = ["/refresh-token", "/api/wx/login-by-nickname"];
        return whiteList.some(url => config.url.endsWith(url))
          ? config
          : new Promise(resolve => {
              const data = getToken();
              if (data) {
                // const now = new Date().getTime();
                // const expired = parseInt(data.expires) - now <= 0;
                // if (expired) {
                //   if (!PureHttp.isRefreshing) {
                //     PureHttp.isRefreshing = true;
                //     // 添加catch处理刷新token失败的情况
                //     useUserStoreHook()
                //       .handRefreshToken({ refreshToken: data.refreshToken })
                //       .then(res => {
                //         const token = res.data.accessToken;
                //         config.headers["Authorization"] = formatToken(token);
                //         PureHttp.requests.forEach(cb => cb(token));
                //         PureHttp.requests = [];
                //       })
                //       .catch(() => {
                //         // 刷新token失败时强制登出
                //         useUserStoreHook().logOut();
                //         window.location.replace("/login");
                //       })
                //       .finally(() => {
                //         PureHttp.isRefreshing = false;
                //       });
                //   }
                //   resolve(PureHttp.retryOriginalRequest(config));
                // } else {
                config.headers["Authorization"] = formatToken(data.token);
                resolve(config);
                // }
              } else {
                resolve(config);
              }
            });
      },
      error => {
        return Promise.reject(error);
      }
    );
  }

  /** 统一处理加载动画关闭逻辑 */
  private handleLoadingClose() {
    setTimeout(() => {
      PureHttp.loadingCount--;
      if (PureHttp.loadingCount <= 0) {
        PureHttp.loadingInstance?.close();
        PureHttp.loadingCount = 0;
      }
    }, 300); // 延迟关闭，防止多次新的loading动画重叠问题
  }

  private httpInterceptorsResponse(): void {
    const instance = PureHttp.axiosInstance;
    instance.interceptors.response.use(
      (response: PureHttpResponse) => {
        const $config = response.config;
        if (response.status === 200 && response.data?.code == 401) {
          // 401代表`token`过期，此时需要刷新`token`
          if (!PureHttp.isRefreshing) {
            PureHttp.isRefreshing = true;
            message("登录状态已过期，请重新登录", { type: "error" });
            // 强制登出
            useUserStoreHook().logOut();
            window.location.replace("/login");
          }
        }
        // 新增业务错误码拦截
        if (response.data?.code !== 200) {
          // 假设200是成功状态码
          console.error("有问题？response", response);
          const error = {
            response,
            code: response.data?.code,
            message: response.data?.message,
            isBusinessError: true
          };
          // 关闭进度条动画
          this.handleLoadingClose();
          // 特殊业务处理 开发阶段隐藏错误信息，生产环境显示错误信息
          // if (import.meta.env.DEV) {
          handleBusinessError(error.code, error.message);
          // }
          return Promise.reject(error);
        }
        // 优先判断post/get等方法是否传入回调，否则执行初始化设置等回调
        if (typeof $config.beforeResponseCallback === "function") {
          $config.beforeResponseCallback(response);
          return response.data;
        }
        if (PureHttp.initConfig.beforeResponseCallback) {
          PureHttp.initConfig.beforeResponseCallback(response);
          return response.data;
        }
        // 关闭进度条动画
        this.handleLoadingClose();
        NProgress.done();
        return response.data;
      },
      (error: PureHttpError) => {
        console.error(error);
        // 新增业务错误类型判断
        if (error.isBusinessError) {
          const { code, message } = error;
          return handleBusinessError(code, message);
        }
        // 原有网络错误处理保持不变...
        const { type, msg, redirect } = handleHttpError(error);
        if (msg) {
          message(msg, {
            type: "error"
          });
        }
        console.error(msg);

        if (redirect) {
          redirectToLogin();
        } else if (type === "SERVER_ERROR") {
          redirectToLogin(); // 服务器错误统一跳转
        }
        // 关闭进度条动画
        this.handleLoadingClose();
        NProgress.done(); // ② 顶部进度条完成

        return Promise.reject(error);
      }
    );
  }

  /** 通用请求工具函数 */
  public request<T>(
    method: RequestMethods,
    url: string,
    param?: AxiosRequestConfig,
    axiosConfig?: PureHttpRequestConfig
  ): Promise<T> {
    const config = {
      method,
      url,
      ...param,
      ...axiosConfig
    } as PureHttpRequestConfig;

    // 单独处理自定义请求/响应回调
    return new Promise((resolve, reject) => {
      PureHttp.axiosInstance
        .request(config)
        .then((response: undefined) => {
          resolve(response);
        })
        .catch(error => {
          reject(error);
        });
    });
  }

  /** 单独抽离的`post`工具函数 */
  public post<T, P>(
    url: string,
    params?: AxiosRequestConfig<P>,
    config?: PureHttpRequestConfig
  ): Promise<T> {
    return this.request<T>("post", url, params, config);
  }

  /** 单独抽离的`get`工具函数 */
  public get<T, P>(
    url: string,
    params?: AxiosRequestConfig<P>,
    config?: PureHttpRequestConfig
  ): Promise<T> {
    return this.request<T>("get", url, params, config);
  }
  /** 单独抽离的`delete`工具函数 */
  public delete<T, P>(
    url: string,
    params?: AxiosRequestConfig<P>,
    config?: PureHttpRequestConfig
  ): Promise<T> {
    return this.request<T>("delete", url, params, config);
  }

  /** 单独抽离的`put`工具函数 */
  public put<T, P>(
    url: string,
    params?: AxiosRequestConfig<P>,
    config?: PureHttpRequestConfig
  ): Promise<T> {
    return this.request<T>("put", url, params, config);
  }

  /** 单独抽离的`upload`文件上传函数 */
  public upload<T>(
    url: string,
    formData: FormData,
    config?: PureHttpRequestConfig
  ): Promise<T> {
    return this.request<T>(
      "post",
      url,
      {
        data: formData,
        headers: {
          "Content-Type": "multipart/form-data"
        }
      },
      config
    );
  }
}

export const http = new PureHttp();
export interface ResultList {
  code: number;
  data: any;
  message: string;
  success: boolean;
}
export interface ResultBoolean {
  code: number;
  data: PageInfoModel;
  message: string;
  success: boolean;
}
export type QueryParams = {
  pageNum?: number; // 当前页码
  pageSize?: number; // 每页显示条数
  [property: string]: any;
};
export type PaginationParams = {
  pageNum: number; // 当前页码
  pageSize: number; // 每页显示条数
  total?: number; // 总条数
  totalPage?: number;
  list?: any[];
};
/**
 * 返回数据
 *
 * PageInfoModel
 */
export type PageInfoModel = {
  endRow?: number;
  hasNextPage?: boolean;
  hasPreviousPage?: boolean;
  isFirstPage?: boolean;
  isLastPage?: boolean;
  list?: any[];
  navigateFirstPage?: number;
  navigateLastPage?: number;
  navigatepageNums?: number[];
  navigatePages?: number;
  nextPage?: number;
  pageNum?: number;
  pages?: number;
  pageSize?: number;
  prePage?: number;
  size?: number;
  startRow?: number;
  total?: number;
  [property: string]: any;
};
